package jfilters.filters.color;

/*
    Copyright Janne Liljeblad 2008.

    This file is part of JFilters.

    JFilters is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    JFilters is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with JFilters.  If not, see <http://www.gnu.org/licenses/>.
*/

import jfilters.filters.SingleInputFilter;
import jfilters.libcolor.*;
import jfilters.libmath.*;
import jfilters.lib.*;
import java.awt.image.BufferedImage;

public class JFHueSat extends SingleInputFilter
{
	private double[] hue = new double[7];
	private double[] lightness = new double[7];
	private double[] saturation = new double[7];

	private int[][] hue_transfer = new int[6][256];
	private int[][] lightness_transfer = new int[6][256];
	private int[][] saturation_transfer = new int[6][256];

	public JFHueSat()
	{
		init();
	}

	public void init()
	{
		for( int partition = JFColorSpace.JF_ALL_HUES; partition <= JFColorSpace.JF_MAGENTA_HUES; partition++)
		{
			hue[partition]        = 0.0;
			lightness[partition]  = 0.0;
			saturation[partition] = 0.0;
		}
		calculate_transfers();
	}

	public void setHSLValues( int huePartition, double h, double s, double l )
	{
		hue[huePartition] = h;
		lightness[huePartition] = l;
		saturation[huePartition] = s;
		calculate_transfers();
	}

	private void calculate_transfers()
	{
		int value;
		int h;
		int i;
		
		/*  Calculate transfers  */
		for (h = 0; h < 6; h++)
			for (i = 0; i < 256; i++)
			{
				value = (int)(( hue[0] + hue[ h + 1]) * 255.0 / 360.0);
				if ((i + value) < 0)
					hue_transfer[ h ][i] = 255 + (i + value);
				else if ((i + value) > 255)
					hue_transfer[ h ][i] = i + value - 255;
				else
					hue_transfer[ h ][i] = i + value;
			
				/*  Lightness  */
				value = (int)(( lightness[0] + lightness[ h + 1]) * 127.0 / 100.0);
				value = JFMath.CLAMP(value, -255, 255);
			
				if (value < 0)
					lightness_transfer[ h ][i] = (int) ((i * (255 + value)) / 255);
				else
					lightness_transfer[ h ][i] = (int) (i + ((255 - i) * value) / 255);
			
				/*  Saturation  */
				value = (int)(( saturation[0] + saturation[h + 1]) * 255.0 / 100.0);
				value = JFMath.CLAMP (value, -255, 255);

				saturation_transfer[ h ][i] = JFMath.CLAMP ((i * (255 + value)) / 255, 0, 255);
			}

	}

	public BufferedImage filter( BufferedImage destImg )
	{
		int    w, h, a;
		int    r, g, b;
		int    newHue;

		int[] dst = getBank( destImg );

		JFRGBInt spix = new JFRGBInt();
		JFHSLInt hpix = new JFHSLInt();
		for( int i = 0; i < dst.length; i++ )
		{
			a = ( dst[ i ] >> alpha ) & 0xff;
			spix.r = ( dst[ i ] >> red ) & 0xff;
			spix.g = ( dst[ i ] >> green ) & 0xff;
			spix.b = dst[ i ] & 0xff;

			JFColorSpace.jimp_rgb_to_hsl_int(spix, hpix);
		
			newHue = (hpix.h + (128 / 6)) / 6;//?????
		
			if (hpix.h < 21)
				newHue = 0;
			else if (hpix.h  < 64)
				newHue = 1;
			else if (hpix.h  < 106)
				newHue = 2;
			else if (hpix.h  < 149)
				newHue = 3;
			else if (hpix.h  < 192)
				newHue = 4;
			else if (hpix.h  < 234)
				newHue = 5;
			else
				newHue = 0;
		
			hpix.h = hue_transfer[newHue][spix.r];
			hpix.s = saturation_transfer[newHue][spix.g];
			hpix.l = lightness_transfer[newHue][spix.b];
		
			JFColorSpace.jimp_hsl_to_rgb_int (hpix, spix);
		
			dst[ i ] = a << alpha | spix.r << red | spix.g << green | spix.b;
		}

		return destImg;
	}

}//end class